/*
 * $Id: onu.c,v 1.1.2.9 Broadcom SDK $
 * $Copyright: Copyright 2011 Broadcom Corporation.
 * This program is the proprietary software of Broadcom Corporation
 * and/or its licensors, and may only be used, duplicated, modified
 * or distributed pursuant to the terms and conditions of a separate,
 * written license agreement executed between you and Broadcom
 * (an "Authorized License").  Except as set forth in an Authorized
 * License, Broadcom grants no license (express or implied), right
 * to use, or waiver of any kind with respect to the Software, and
 * Broadcom expressly reserves all rights in and to the Software
 * and all intellectual property rights therein.  IF YOU HAVE
 * NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE
 * IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE
 * ALL USE OF THE SOFTWARE.  
 *  
 * Except as expressly set forth in the Authorized License,
 *  
 * 1.     This program, including its structure, sequence and organization,
 * constitutes the valuable trade secrets of Broadcom, and you shall use
 * all reasonable efforts to protect the confidentiality thereof,
 * and to use this information only in connection with your use of
 * Broadcom integrated circuit products.
 *  
 * 2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS
 * PROVIDED "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES,
 * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY,
 * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE.  BROADCOM SPECIFICALLY
 * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
 * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES,
 * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
 * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING
 * OUT OF USE OR PERFORMANCE OF THE SOFTWARE.
 * 
 * 3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL
 * BROADCOM OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL,
 * INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER
 * ARISING OUT OF OR IN ANY WAY RELATING TO YOUR USE OF OR INABILITY
 * TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF
 * THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR USD 1.00,
 * WHICHEVER IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING
 * ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.$
 *
 * File:    onu.c
 * Purpose:     Tracks and manages onu chip.
 *      
 */
#include <assert.h>
#include <sal/core/libc.h>
#include <sal/appl/config.h>
#include <soc/drv.h>
#include <soc/ctrl_if.h>
     
#include <soc/debug.h>
#include <soc/ea/TkDefs.h>
#include <soc/ea/ea_drv.h>
#include "tk3715.h"
#include <soc/ea/TkOnuApi.h>
#include <soc/ea/CtcMiscApi.h>
#include <soc/ea/onu.h>

int 
_soc_ea_load_info_get(int32 unit, soc_ea_load_info_t *load_info)
{
    int rv = SOC_E_NONE;
    
    if(NULL == load_info){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlLoadInfo);

    if(SOC_E_NONE != rv){
        return rv;
    }

    sal_memcpy(load_info, SOC_EA_PRIVATE(unit)->load_info, 
        sizeof(soc_ea_load_info_t)*socEaFileCount);
    
    return SOC_E_NONE;
}

/* here are the onu information part */
int
_soc_ea_firmware_ver_get(int unit, uint16 *ver)
{
    int rv = SOC_E_NONE;
    
    if(NULL == ver){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlOnuInfo);

    if(SOC_E_NONE != rv){
        return rv;
    }

    *ver = SOC_EA_PRIVATE(unit)->onu_info.firmware_ver;
    
    return SOC_E_NONE;
}

int 
_soc_ea_revision_id_get(int unit, uint32 *rev)
{
    int rv = SOC_E_NONE;
    
    if(NULL == rev){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlRevisionId);

    if(SOC_E_NONE != rv){
        return rv;
    }

    *rev = SOC_EA_PRIVATE(unit)->chip_revision;
    
    return SOC_E_NONE;
}

int 
_soc_ea_vendor_id_get(int unit, soc_ea_extend_id_t id)
{
    int rv = SOC_E_NONE;
    
    if(NULL == id){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlVendorId);

    if(SOC_E_NONE != rv){
        return rv;
    }

    sal_memcpy(id, SOC_EA_PRIVATE(unit)->extend_id, SOC_EA_EXTEND_ID_LEN);
    
    return SOC_E_NONE;
}


int
_soc_ea_ctc_oam_ver_get(int unit, uint32 *ver)
{
    int rv = SOC_E_NONE;
    
    if(NULL == ver){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlCtcOamVer);

    if(SOC_E_NONE != rv){
        return rv;
    }

    *ver = SOC_EA_PRIVATE(unit)->oam_ver;
    return SOC_E_NONE;
}

int
_soc_ea_real_llid_count_get(int unit, uint32 *llid_count)
{
    int rv = SOC_E_NONE;

    if(NULL == llid_count){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit, socEaChipInfoControlLllidCount);

    if(SOC_E_NONE == rv){
        *llid_count = SOC_EA_PRIVATE(unit)->llid_count;
    }

    return rv;
}

int
_soc_ea_info_get(int unit, soc_ea_onu_info_t *info)
{
    int rv = SOC_E_NONE;

    if(NULL == info){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit, socEaChipInfoControlOnuInfo);

    if(SOC_E_NONE == rv){
        sal_memcpy(info, &(SOC_EA_PRIVATE(unit)->onu_info), sizeof(soc_ea_onu_info_t));
    }

    return rv;
}

/*
 * Function:
 *      _soc_ea_mllid_set
 * Description:
 *      Enable, disable multiple llid or notify pon firmware the authentication 
 *      successful or not.
 * Parameters:
 *      unit  - (IN) BCM device number
 *      count - (IN) 0 authentication fail, 1 to the count of max count of llid 
 *            the pon chipset support means enable multiple llid, max count add 1
 *            means authentication sucessfull.
 * Returns     : SOC_E_XXX
 */
int 
_soc_ea_mllid_set(int unit, uint32 count)
{
    int rv;
    
    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;   
    }
    
    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlOnuInfo);

    if(SOC_E_NONE != rv){
        return rv;
    }

    if(!count){
        rv = TkExtOamSetCTCLoidAuthIfFail(unit, 0, TRUE);
    }else if(count <= SOC_EA_PRIVATE(unit)->onu_info.max_link_count){
        rv = CtcExtOamSetMulLlidCtrl(unit, count);    
        if(rv != SOC_E_NONE){
            rv = SOC_E_FAIL;
        }else{
            SOC_EA_CONTROL_MLLID_NUM(unit) = count;
        }
    }else if(count == (SOC_EA_PRIVATE(unit)->onu_info.max_link_count+1)){
        rv = TkExtOamSetCTCLoidAuthIfFail(unit, 0, FALSE);
    }else{
        return SOC_E_PARAM;
    }

    if(rv != SOC_E_NONE){
        rv = SOC_E_FAIL;
    }

    return rv;
}

/*
 * Function:
 *      _soc_ea_mllid_get
 * Description:
 *      Get state of Enable, disable multiple llid or notify pon firmware the 
 *      authentication successful or not.
 * Parameters:
 *      unit  - (IN) BCM device number
 *      count - (IN) 0 authentication fail, 1 to the count of max count of llid 
 *            the pon chipset support means enable multiple llid
 * Returns     : SOC_E_XXX
 */
int 
_soc_ea_mllid_get(int unit, uint32 *count)
{
    int rv;
    uint8 auth_state;
    
    if(NULL == count){
        return SOC_E_PARAM;
    }
    
    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;   
    }

    rv = TkExtOamGetCTCLoidAuthIfFail(unit, 0, &auth_state);
    if(rv != SOC_E_NONE){
        return SOC_E_FAIL;
    }

    if(TRUE == auth_state){
        *count = 0;
    }else{
        *count = SOC_EA_CONTROL_MLLID_NUM(unit);
    }
    
    return SOC_E_NONE;
}

/*
 * Function:
 *      _soc_ea_gpio_write
 * Description:
 *      Write a GPIO value belonged to the bank, only the bits masked by the mask will be 
 *      write to the gpio register.
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      mask - (IN) Bits mask
 *      data - (IN) Value to be write to the GPIO
 * Returns     : SOC_E_XXX
 */
int
_soc_ea_gpio_write(int unit, uint32 flags, uint32 mask, uint32 data)
{
    int rv = SOC_E_NONE;

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    flags = flags;
    rv = TkExtOamSetGpio(unit, 0, mask, data);

    if(rv != SOC_E_NONE){
        return SOC_E_FAIL;
    }
    
    return SOC_E_NONE; 
}

/*
 * Function:
 *      _soc_ea_gpio_read
 * Description:
 *      Read a GPIO value belonged to the bank
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      data - (OUT) Value read out
 * Returns     : SOC_E_XXX
 */
int 
_soc_ea_gpio_read(int unit, uint32 flags, uint32 *data)
{
    int rv = SOC_E_NONE;

    if(NULL == data){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    flags = flags;
    rv = TkExtOamGetGpio(unit, 0, data);

    if(rv != SOC_E_NONE){
        return SOC_E_FAIL;
    }
    
    return SOC_E_NONE; 
}

/*
 * Function:
 *      _soc_ea_gpio_config_write
 * Description:
 *      Wirte the gpio configuration
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      mask - (IN) Bits mask
 * Returns     : SOC_E_XXX
 */
int
_soc_ea_gpio_config_write(int unit, uint32 flags, uint32 mask)
{
    int rv = SOC_E_NONE;

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    flags = flags;
    rv = TkExtOamSetGpioConfig(unit, 0, mask);

    if(rv != SOC_E_NONE){
        return SOC_E_FAIL;
    }
    
    return SOC_E_NONE; 
}

/*
 * Function:
 *      _soc_ea_gpio_config_read
 * Description:
 *      Read the gpio configuration
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      mask - (OUT) Value read out
 * Returns     : SOC_E_XXX
 */
int 
_soc_ea_gpio_config_read(int unit, uint32 flags, uint32 *mask)
{
    int rv = SOC_E_NONE;

    if(NULL == mask){
        return SOC_E_PARAM;
    }

    if(!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    flags = flags;
    rv = TkExtOamGetGpioConfig(unit, 0, mask);

    if(rv != SOC_E_NONE){
        return SOC_E_FAIL;
    }
    
    return SOC_E_NONE; 
}

/*
 * Function:
 *      soc_gpio_write
 * Description:
 *      Write a GPIO value belonged to the bank, only the bits masked by the mask will be 
 *      write to the gpio register.
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      mask - (IN) Bits mask
 *      data - (IN) Value to be write to the GPIO
 * Returns     : SOC_E_XXX
 */
int
soc_gpio_write(int unit, uint32 flags, uint32 mask, uint32 data)
{
    return _soc_ea_gpio_write(unit, flags, mask, data);
}

/*
 * Function:
 *      soc_gpio_read
 * Description:
 *      Read a GPIO value belonged to the bank
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      data - (OUT) Value read out
 * Returns     : SOC_E_XXX
 */
int 
soc_gpio_read(int unit, uint32 flags, uint32 *data)
{
    return _soc_ea_gpio_read(unit, flags, data);
}

/*
 * Function:
 *      soc_gpio_config_write
 * Description:
 *      Set Bitmask of GPIO ports for which to generate alert.  Allow the host to be notified 
 *      of changes at the GPIO ports of an ONU through alerts
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      mask - (IN) Bits mask
 * Returns     : SOC_E_XXX
 */
int
soc_gpio_config_write(int unit, uint32 flags, uint32 mask)
{
    return _soc_ea_gpio_config_write(unit, flags, mask);
}

/*
 * Function:
 *      soc_gpio_config_read
 * Description:
 *      Get Bitmask of GPIO ports for which to generate alert.  Allow the host to be notified 
 *      of changes at the GPIO ports of an ONU through alerts
 * Parameters:
 *      unit  - (IN) BCM device number
 *      flags - (IN) BANK flag
 *      mask - (OUT) Value read out
 * Returns     : SOC_E_XXX
 */
int 
soc_gpio_config_read(int unit, uint32 flags, uint32 *mask)
{
    return _soc_ea_gpio_config_read(unit, flags, mask);
}

/*
 * Function:
 *      soc_base_mac_set
 * Description:
 *      Allow user to change the PON base mac which is used form MPCP registering and OAM 
 *      source MAC address. 
 *      If enable multiple llid feature, the llids' mac address will generated from this mac 
 *      address by +1.
 *      The uni base mac address is used for uni port such as the pause frame which come 
 *      from the uni port will pack this mac as the source mac. uni0 will have this mac while
 *      uni1 use uni_base_mac +1, so do other unis
 * Parameters:
 *      unit  - (IN) BCM device number
 *      mac - (IN) Including the PON base mac and UNI base mac
 * Returns     : SOC_E_XXX
 */
int 
soc_base_mac_set(int unit, soc_base_mac_t mac)
{
    int rv = SOC_E_NONE;
    OamEponBaseMac base_mac;
    
    if (!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }
    
    sal_memcpy(base_mac.PonBaseMac, mac.pon_base_mac, sizeof(sal_mac_addr_t));
    sal_memcpy(base_mac.UserBaseMac, mac.uni_base_mac, sizeof(sal_mac_addr_t));
   
    rv = TkExtOamSetEponBaseMac(unit, &base_mac);
    
    if (SOC_E_NONE == rv) {
        sal_memcpy(SOC_EA_PRIVATE(unit)->onu_info.pon_base_mac,mac.pon_base_mac, 
            sizeof(sal_mac_addr_t));
        sal_memcpy(SOC_EA_PRIVATE(unit)->onu_info.uni_base_mac,mac.uni_base_mac,
            sizeof(sal_mac_addr_t));   
        return SOC_E_NONE;
    } else {
        return SOC_E_FAIL;
    }
}

/*
 * Function:
 *      soc_base_mac_get
 * Description:
 *      Allow user to get the PON base mac which is used form MPCP registering and OAM 
 *      source MAC address. 
 *      If enable multiple llid feature, the llids' mac address will generated from this mac 
 *      address by +1.
 *      The uni base mac address is used for uni port such as the pause frame which come 
 *      from the uni port will pack this mac as the source mac. uni0 will have this mac while
 *      uni1 use uni_base_mac +1, so do other unis
 * Parameters:
 *      unit  - (IN) BCM device number
 *      mac - (IN) Including the PON base mac and UNI base mac
 * Returns     : SOC_E_XXX
 */
int 
soc_base_mac_get(int unit, soc_base_mac_t *mac)
{
    int rv = SOC_E_NONE;

    if (NULL == mac) {
        return SOC_E_PARAM;
    }
    
    if (!SOC_IS_EA(unit)){
        return SOC_E_UNIT;
    }

    rv = _soc_ea_chip_info_sync(unit,socEaChipInfoControlOnuInfo);

    if(SOC_E_NONE != rv){
        return rv;
    }

    sal_memcpy(mac->pon_base_mac,SOC_EA_PRIVATE(unit)->onu_info.pon_base_mac, 
        sizeof(sal_mac_addr_t));
    sal_memcpy(mac->uni_base_mac,SOC_EA_PRIVATE(unit)->onu_info.uni_base_mac,
        sizeof(sal_mac_addr_t));

    return SOC_E_NONE;
}
